package com.tanhua.dubbo.server.api;

import com.alibaba.dubbo.common.utils.CollectionUtils;
import com.alibaba.dubbo.config.annotation.Service;
import com.mongodb.client.result.DeleteResult;
import com.tanhua.dubbo.server.pojo.*;
import com.tanhua.dubbo.server.service.IdService;
import com.tanhua.dubbo.server.vo.PageInfo;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;

import java.util.ArrayList;
import java.util.List;

/**
 * @ClassName :  MomentsApiImpl
 * @Author : Tenebrous
 * @Date: 2020/12/12 20:05
 * @Description : 朋友圈实现类
 */
@Service(version = "1.0.0")
public class MomentsApiImpl implements MomentsApi {

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private IdService idService;

    /**
     * 1、发布动态
     *
     * @param publish 动态信息表
     * @return 主键id
     */
    @Override
    public String savePublish(Publish publish) {

        
        // 校验publish对象
        if (publish.getUserId() == null) {
            return null;
        }

        try {
            // 设置id
            publish.setId(ObjectId.get());
            // 设置发布时间
            publish.setCreated(System.currentTimeMillis());
            // 设置朋友全查看权限
            publish.setSeeType(1);

            // 增加一个自增长的pid
            publish.setPid(this.idService.createdId("publish", publish.getId().toHexString()));

            /*在动态发布之后,不立马将该条动态存入到发布表,相册表以及好友时间线表.而是在这里对publish动态进行
            * moment强化封装,初始每条动态的审核状态值都是1:待审核状态,然后在此处设置一个机器自动审查方法,将带有
            * 初步审查后的审核状态值得moment存入到MongoDB中,在后端查询遍历的过程之中,对满足审核状态为通过的动态
            * 进行保存到三个表中的操作
            * */
            
            // 对该条publish进行强化封装
            Moments moments = new Moments();
            moments.setUserId(publish.getUserId());  // 设置用户ID
            moments.setCreateDate(publish.getCreated()); // 设置动态创建时间
            moments.setMedias(publish.getMedias());  // 设置medias
            moments.setText(publish.getText()); // 设置文本内容
            moments.setId(publish.getId().toHexString()); // 设置动态ID
            moments.setReportCount(0); // 设置举报数量,刚发布的动态初始值设置为0
            moments.setLikeCount(0); // 设置点赞数量,刚发布的动态初始值设置为0
            moments.setCommentCount(0); // 设置评论数量,刚发布的动态初始值设置为0
            moments.setForwardingCount(0); // 设置转发数量,刚发布的动态初始值设置为0
            
            // 向moments中设置publish的数据
            moments.setLocationName(publish.getLocationName());
            moments.setLatitude(publish.getLatitude());
            moments.setLongitude(publish.getLongitude());
            moments.setNotSeeList(publish.getNotSeeList());
            moments.setSeeList(publish.getSeeList());
            moments.setSeeType(publish.getSeeType());
            moments.setPid(publish.getPid());
            moments.setOid(publish.getId());
            
            // 这个时候的审核状态值都是为待机器审核,设置为1
            moments.setState("wait");
            
            // 这里设置一个机器审核功能.现在就按照机器审核全部通过来做
            // 如果机器审核通过,直接发布三张表,如果不通过,返回null
            moments.setState("auto_pass");
            
            if (moments.getState().equals("auto_pass")){
                // 如果审核状态为自动审核通过,直接发布三张表
    
                // -------------------------1、写入发布表----------------------------------------------
                // 保存动态信息
                this.mongoTemplate.save(publish);
    
                // --------------------------2、写入自己的相册表中----------------------------------------
                // 写入自己的相册表中
                Album album = new Album();
                album.setId(ObjectId.get());
                // 朋友圈动态id
                album.setPublishId(publish.getId());
                // 发布时间
                album.setCreated(System.currentTimeMillis());
                // 写入mongodb中, 表名为moments_album_{id}
                this.mongoTemplate.save(album, "quanzi_album_" + publish.getUserId());
    
                // --------------------------3、写入好友时间线中------------------------------------------------
                // 查询当前用户的好友数据，将动态数据写入到好友的时间线表中
                Criteria criteria = Criteria.where("userId").is(publish.getUserId());
                Query query = Query.query(criteria);
                List<Users> users = this.mongoTemplate.find(query, Users.class);
                for (Users user : users) {
                    TimeLine timeLine = new TimeLine();
                    timeLine.setId(ObjectId.get());
                    timeLine.setPublishId(publish.getId());
                    timeLine.setUserId(user.getUserId());
                    timeLine.setDate(System.currentTimeMillis());
                    this.mongoTemplate.save(timeLine, "quanzi_time_line_" + user.getFriendId());
                }
                
                // 将moment存入mongo
                this.mongoTemplate.save(moments);
                
                return publish.getId().toHexString();
                
            }
            // 将moment存入mongo
            this.mongoTemplate.save(moments);
            
        } catch (Exception e) {
            e.printStackTrace();
            // TODO 出错的事务回滚
        }
        return null;
    }

    /**
     * 2、查询动态
     *
     * @param userId   登录者id
     * @param page     页数
     * @param pageSize 页大小
     * @return 分页参数及动态信息
     */
    @Override
    public PageInfo<Publish> queryPublishList(Long userId, Integer page, Integer pageSize) {
        //-----------------------------------1、查询时间线------------------------------------------
        // 分页条件
        PageRequest pageRequest = PageRequest.of(page - 1, pageSize, Sort.by(Sort.Order.desc("created")));
        Query query = new Query().with(pageRequest);

        String tableName = "quanzi_time_line_";
        if (null == userId) {
            // 未传入用户id，则表示查询推荐时间线表
            tableName += "recommend";
        } else {
            tableName += userId;
        }

        //查询自己的时间线表，
        //查询的仅仅是时间线，具体的内容需要查询里面的publish表
        List<TimeLine> timeLineList = this.mongoTemplate.find(query, TimeLine.class, tableName);

        //-----------------------------------2、查询发布表----------------------------------------
        // 定义一个发布动态id的集合
        List<ObjectId> publishIds = new ArrayList<>();
        // 遍历取出publishId
        for (TimeLine timeLine : timeLineList) {
            publishIds.add(timeLine.getPublishId());
        }
        //查询发布信息
        // 条件：id是否在publishIds中
        Query queryPublish = Query.query(Criteria.where("id")
                .in(publishIds))
                .with(Sort.by(Sort.Order.desc("created")));
        // 查询发布表
        List<Publish> publishList = this.mongoTemplate.find(queryPublish, Publish.class);
        // 封装分页对象
        PageInfo<Publish> pageInfo = new PageInfo<>();
        // 设置参数
        pageInfo.setPageNum(page);
        pageInfo.setPageSize(pageSize);
        pageInfo.setRecords(publishList);
        // 不提供总数
        pageInfo.setTotal(0);
        return pageInfo;
    }

    /**
     * 3、点赞功能
     *
     * @param userId    登录者id
     * @param publishId 朋友圈动态id
     * @return 布尔值
     */
    @Override
    public boolean saveLikeComment(Long userId, String publishId) {
        // 判断是否已经点赞，如果已经点赞就返回, 思路：查询点赞数
        // 条件：userId==登录者id，publishId==动态id，commentType==1；
        Criteria criteria = Criteria.where("userId").is(userId)
                .and("publishId").is(new ObjectId(publishId))
                .and("commentType").is(1);
        Query query = Query.query(criteria);
        // 查询点赞数
        long count = this.mongoTemplate.count(query, Comment.class);
        System.out.println("saveLikeComment" + "----------------" + count);
        // 如果count>0
        if (count > 0) {
            // 代表已经点过赞了
            return false;
        }
        // 将评论类型传给发布评论方法
        return this.saveComment(userId, publishId, 1, null);
    }

    /**
     * 4、取消点赞
     *
     * @param userId      登录者id
     * @param publishId   朋友圈动态id
     * @param commentType 评论类型
     * @return 布尔值
     */
    @Override
    public boolean removeComment(Long userId, String publishId, Integer commentType) {
        // 条件：userId==登录者id，publishId==动态id，commentType==3；
        Criteria criteria = Criteria.where("userId").is(userId)
                .and("publishId").is(new ObjectId(publishId))
                .and("commentType").is(commentType);
        Query query = Query.query(criteria);
        // 查询点赞数
        DeleteResult deleteResult = this.mongoTemplate.remove(query, Comment.class);
        return deleteResult.getDeletedCount() > 0;
    }

    /**
     * 5、喜欢功能
     *
     * @param userId    登录者id
     * @param publishId 朋友圈动态id
     * @return 布尔值
     */
    @Override
    public boolean saveLoveComment(Long userId, String publishId) {
        // 判断是否已经喜欢，如果已经喜欢就返回
        // 条件：userId==登录者id，publishId==动态id，commentType==3；
        Criteria criteria = Criteria.where("userId").is(userId)
                .and("publishId").is(new ObjectId(publishId))
                .and("commentType").is(3);
        Query query = Query.query(criteria);
        // 查询点赞数
        long count = this.mongoTemplate.count(query, Comment.class);
        // 如果count>0
        if (count > 0) {
            // 代表已经点过赞了
            return false;
        }
        // 将评论类型传给发布评论方法
        return this.saveComment(userId, publishId, 3, null);
    }

    /**
     * 6、发布评论
     *
     * @param userId    登录者id
     * @param publishId 朋友圈动态id
     * @param type      评论类型
     * @param content   评论内容
     * @return 布尔值
     */
    @Override
    public boolean saveComment(Long userId, String publishId, Integer type, String content) {
        try {
            // 创建Comment对象
            Comment comment = new Comment();
            // 将前端传来的值设置进去
            comment.setContent(content);
            comment.setIsParent(true);
            comment.setCommentType(type);
            comment.setPublishId(new ObjectId(publishId));
            comment.setUserId(userId);
            comment.setId(ObjectId.get());
            comment.setCreated(System.currentTimeMillis());

            // 设置发布人的id
            Publish publish = this.mongoTemplate.findById(comment.getPublishId(), Publish.class);
            if (null != publish) {
                comment.setPublishUserId(publish.getUserId());
            } else {
                Video video = this.mongoTemplate.findById(comment.getPublishId(), Video.class);
                if (null != video) {
                    comment.setPublishUserId(video.getUserId());
                }
            }
            // 保存到mongodb中
            this.mongoTemplate.save(comment);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 7、查询评论数量
     *
     * @param publishId 登录者id
     * @param type      评论类型
     * @return 布尔值
     */
    @Override
    public Long queryCommentCount(String publishId, Integer type) {
        Criteria criteria = Criteria.where("publishId").is(new ObjectId(publishId))
                .and("commentType").is(type);
        Query query = Query.query(criteria);
        return this.mongoTemplate.count(query, Comment.class);
    }

    /**
     * 8、根据id查询动态信息
     *
     * @param publishId 朋友圈动态id
     * @return 动态信息
     */
    @Override
    public Publish queryPublishById(String publishId) {
        return this.mongoTemplate.findById(new ObjectId(publishId), Publish.class);
    }

    /**
     * 查询评论
     *
     * @param publishId 动态id
     * @param page      页码
     * @param pageSize  每页数量
     * @return 分页参数
     */
    @Override
    public PageInfo<Comment> queryCommentList(String publishId, Integer page, Integer pageSize) {
        PageRequest pageRequest = PageRequest.of(page - 1, pageSize, Sort.by(Sort.Order.asc("created")));
        Query query = Query.query(Criteria.where("publishId").is(new ObjectId(publishId))
                .and("commentType").is(2)).with(pageRequest);
        // 查询评论信息
        List<Comment> commentList = this.mongoTemplate.find(query, Comment.class);
        // 设置pageInfo参数
        PageInfo<Comment> pageInfo = new PageInfo<>();
        pageInfo.setTotal(0);
        pageInfo.setPageSize(pageSize);
        pageInfo.setPageNum(page);
        pageInfo.setRecords(commentList);
        return pageInfo;
    }

    /**
     * 查询某一用户的评论
     *
     * @param userId   用户id
     * @param type     评论类型
     * @param page     页码
     * @param pageSize 每页条数
     * @return 分页参数
     */
    @Override
    public PageInfo<Comment> queryCommentListByUser(Long userId, Integer type, Integer page, Integer pageSize) {
        PageRequest pageRequest = PageRequest.of(page - 1, pageSize, Sort.by(Sort.Order.desc("created")));
        Query query = new Query(Criteria
                .where("publishUserId").is(userId)
                .and("commentType").is(type)).with(pageRequest);

        List<Comment> commentList = this.mongoTemplate.find(query, Comment.class);

        PageInfo<Comment> pageInfo = new PageInfo<>();
        pageInfo.setPageNum(page);
        pageInfo.setPageSize(pageSize);
        pageInfo.setRecords(commentList);
        //不提供总数
        pageInfo.setTotal(0);
        return pageInfo;
    }

    /**
     * 根据pid批量查询数据
     *
     * @param pids 朋友圈动态id
     * @return 集合
     */
    @Override
    public List<Publish> queryPublishByPids(List<Long> pids) {
        Query query = Query.query(Criteria.where("pid").in(pids));
        return this.mongoTemplate.find(query, Publish.class);
    }

    @Override
    public PageInfo<Publish> queryAlbumList(Long userId, Integer page, Integer pageSize) {
        PageInfo<Publish> pageInfo = new PageInfo<>();
        pageInfo.setPageNum(page);
        pageInfo.setPageSize(pageSize);
        //不提供总数
        pageInfo.setTotal(0);

        PageRequest pageRequest = PageRequest.of(page - 1, pageSize, Sort.by(Sort.Order.desc("created")));
        Query query = new Query().with(pageRequest);
        List<Album> albumList = this.mongoTemplate.find(query, Album.class, "quanzi_album_" + userId);

        if (CollectionUtils.isEmpty(albumList)) {
            return pageInfo;
        }
        List<ObjectId> publishIds = new ArrayList<>();
        for (Album album : albumList) {
            publishIds.add(album.getPublishId());
        }

        //查询发布信息
        Query queryPublish = Query.query(Criteria.where("id").in(publishIds)).with(Sort.by(Sort.Order.desc("created")));
        List<Publish> publishList = this.mongoTemplate.find(queryPublish, Publish.class);
        pageInfo.setRecords(publishList);

        return pageInfo;
    }
}
